using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

using EntLibContrib.Common.Configuration;
using System.Xml;

namespace EntLibContrib.Common.Tests.Configuration
{
    [TestClass]
    public class TypeConfigurationElementFixture
    {
        [TestMethod, DeploymentItem(@"Configuration\TypeConfigurationElement.config")]
        public void Read_Polymorphic_Configuration()
        {
            IConfigurationSource configurationSource = new FileConfigurationSource("TypeConfigurationElement.config");

            FooSettings settings = (FooSettings)configurationSource.GetSection("fooSample");

            Assert.AreEqual("Hello", settings.FooA.Element.Base);

            Assert.IsInstanceOfType(settings.FooB.Element, typeof(DerivedFooElement));
            Assert.AreEqual("World", settings.FooB.Element.Base);
            Assert.AreEqual(2, ((DerivedFooElement)settings.FooB.Element).Derived);
        }

        [TestMethod, DeploymentItem(@"Configuration\TypeConfigurationElement.config")]
        public void Write_Polymorphic_Configuration()
        {
            IConfigurationSource configurationSource = new FileConfigurationSource("TypeConfigurationElement.config");

            FooSettings settings = new FooSettings();

            FooElement baseFoo = new FooElement();
            baseFoo.Base = "Hot";

            settings.FooA.Element = baseFoo;

            DerivedFooElement derivedFoo = new DerivedFooElement();
            derivedFoo.Base = "Stuff";
            derivedFoo.Derived = 3;

            settings.FooB.Element = derivedFoo;

            configurationSource.Add(new FileConfigurationParameter("TypeConfigurationElement.config"), "fooSample", settings);
        }

        public class FooSettings : SerializableConfigurationSection
        {
            private const string FooAPropertyName = "fooA";
            private const string FooBPropertyName = "fooB";

            [ConfigurationProperty(FooAPropertyName, IsRequired = true)]
            public TypeConfigurationElement<FooElement> FooA
            {
                get { return (TypeConfigurationElement<FooElement>)base[FooAPropertyName]; }
                set { base[FooAPropertyName] = value; }
            }

            [ConfigurationProperty(FooBPropertyName, IsRequired = true)]
            public TypeConfigurationElement<FooElement> FooB
            {
                get { return (TypeConfigurationElement<FooElement>)base[FooBPropertyName]; }
                set { base[FooBPropertyName] = value; }
            }
        }

        public class FooElement : ConfigurationElement
        {
            private const string BasePropertyName = "base";

            [ConfigurationProperty(BasePropertyName, IsRequired = true)]
            public string Base
            {
                get { return (string)base[BasePropertyName]; }
                set { base[BasePropertyName] = value; }
            }
        }

        public class DerivedFooElement : FooElement
        {
            private const string DerivedPropertyName = "derived";

            [ConfigurationProperty(DerivedPropertyName, IsRequired = true)]
            public int Derived
            {
                get { return (int)base[DerivedPropertyName]; }
                set { base[DerivedPropertyName] = value; }
            }
        }
    }
}
